package com.hz.copyingsystem.controller;

import com.hz.common.utils.Download;
import com.hz.common.utils.R;
import com.hz.common.utils.ResponseData;
import com.hz.copyingsystem.entity.*;
import com.hz.copyingsystem.feign.OssFeign;
import com.hz.copyingsystem.service.CopybookCharacterInformationService;
import com.hz.copyingsystem.service.FixedInformationDicService;
import com.hz.copyingsystem.vo.*;
import com.hz.utils.FixedInformationName;
import com.hz.utils.MD5;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @author cyl_txw
 * @email cyl_txw@gmail.com
 * @date 2023-05-09 15:02:11
 */
@RestController
@RequestMapping("copybook")
@Api(tags = "字帖")
public class CopybookController {
    @Autowired
    private FixedInformationDicService fixedInformationDicService;

    @Autowired
    private CopybookCharacterInformationService copybookCharacterInformationService;

    @Autowired
    private OssFeign ossFeign;

    /**
     * 根据搜索内容获取字典的简体字
     */
    @ApiOperation("根据搜索内容获取字典的简体字")
    @PostMapping("/stiffTypeface/get")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "content", value = "搜索内容", paramType = "query", dataType = "String", required = true),
    })
    public ResponseData<String> stiffTypefaceGet(@RequestParam("content") String content) {
        if (content == null || content.equals(""))
            return ResponseData.success("请输入检索内容",false);
        CbStiffTypefaceEntity cbStiffTypeface = copybookCharacterInformationService.getCbStiffTypefaceByContent(content);
        if (cbStiffTypeface == null)
            return ResponseData.success("字典不存在该字的简体字",false);
        return ResponseData.success(cbStiffTypeface.getTypeface());
    }


    /**
     * 字帖所有书体、书家获取
     */
    @ApiOperation("字帖所有书体、书家获取")
    @GetMapping("/tc/get")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "查询类别。1字体，2书家", paramType = "query", dataType = "Integer", allowableValues = "1,2", required = true)
    })
    public ResponseData tcGet(@RequestParam("type") Integer type) {
        // 查询所有的字体、书家名称
        List<FixedInformationDicEntity> fixedInformationDicList;
        // 映射成vo List
        switch (type){
            case 1 :
                fixedInformationDicList = fixedInformationDicService.queryByName(FixedInformationName.CO_CHR_CHARACTER_TYPE);
                List<CopybookCharacterTypeVo> copybookCharacterTypeList = fixedInformationDicList.stream()
                        .map(fixedInformationDic -> new CopybookCharacterTypeVo(fixedInformationDic.getId(),
                                fixedInformationDic.getFixedInformationContent(),
                                fixedInformationDic.getUpdatetime(),
                                fixedInformationDic.getIorder()))
                        .collect(Collectors.toList());
                return ResponseData.success(copybookCharacterTypeList);
            case 2 :
                fixedInformationDicList = fixedInformationDicService.queryByName(FixedInformationName.CO_CHR_CALLIGRAPHER);
                List<CopybookCalligrapherVo> copybookCalligrapherList = fixedInformationDicList.stream()
                        .map(fixedInformationDic -> new CopybookCalligrapherVo(fixedInformationDic.getId(),
                                fixedInformationDic.getFixedInformationContent(),
                                fixedInformationDic.getUpdatetime(),
                                fixedInformationDic.getIorder()))
                        .collect(Collectors.toList());
                return ResponseData.success(copybookCalligrapherList);
        }
        return ResponseData.success("类别参数错误！", false);
    }


    /**
     * 根据搜索内容获取字帖字
     */
    @ApiOperation("根据搜索内容获取字帖字")
    @PostMapping("/copybookcharacter/get")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "content", value = "搜索内容", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "characterType", value = "字体类别", paramType = "query", dataType = "String", required = false),
            @ApiImplicitParam(name = "calligrapherFirst", value = "书家首选", paramType = "query", dataType = "String", required = false),
            @ApiImplicitParam(name = "calligrapherSecond", value = "书家次选", paramType = "query", dataType = "String", required = false),
            @ApiImplicitParam(name = "calligrapherLast", value = "书家末选", paramType = "query", dataType = "String", required = false)
    })
    public ResponseData<List<CopybookCharacterInformationVo>> copybookCharacterGet(@RequestParam("content") String content,
                                             @RequestParam(value = "characterType",required = false) String characterType,
                                             @RequestParam(value = "calligrapherFirst",required = false) String calligrapherFirst,
                                             @RequestParam(value = "calligrapherSecond",required = false) String calligrapherSecond,
                                             @RequestParam(value = "calligrapherLast",required = false) String calligrapherLast) {
        if (content == null || content.equals(""))
            return ResponseData.success("请输入检索内容",false);
        // 组成书家list
        List<String> calligrapherList = new ArrayList<>();
        if (calligrapherFirst != null && !calligrapherFirst.equals("")) calligrapherList.add(calligrapherFirst);
        if (calligrapherSecond != null && !calligrapherSecond.equals("")) calligrapherList.add(calligrapherSecond);
        if (calligrapherLast != null && !calligrapherLast.equals("")) calligrapherList.add(calligrapherLast);

        // 单字检索
        char[] characters = content.toCharArray();
        List<CopybookCharacterInformationVo> CopybookCharacterInformationList = new ArrayList<>();
        for (char character: characters) {
            CopybookCharacterInformationVo copybookCharacterInformationVo = copybookCharacterInformationService.getCopybookCharacter(character,
                    characterType,
                    calligrapherList);
            if (copybookCharacterInformationVo != null)
                CopybookCharacterInformationList.add(copybookCharacterInformationVo);
            else{
                // 如果为空，再次检索
                CopybookCharacterInformationVo copybookCharacterInformationCre = new CopybookCharacterInformationVo();
                copybookCharacterInformationCre.setId((long) -1);
                // 根据字体条件检索字帖信息List
                List<CopybookCharacterInformationEntity> copybookCharacterInformationList = copybookCharacterInformationService.getCbCharaInforListByContent(character);
                copybookCharacterInformationCre.setList(copybookCharacterInformationList);
                CopybookCharacterInformationList.add(copybookCharacterInformationCre);
            }
        }
        return ResponseData.success(CopybookCharacterInformationList);
    }


    /**
     * 生成字帖图片
     */
    @ApiOperation("生成字帖图片")
    @PostMapping("/copybookcharacterpic/get")
    public ResponseData copybookCharacterPicGet(@RequestBody CopybookIdsVo copybookIdsVo, @RequestHeader("Authorization") String token) {
        // 1.根据id查询图片url
        List<Long> idList = copybookIdsVo.getIds();
        if (idList == null || idList.size() < 1)
            return ResponseData.success("未生成书法图片", false);
        List<CopybookCharacterInformationEntity> copybookCharacterInformationList = copybookCharacterInformationService.getCopybookCharacterInforByIds(idList);

        // 2.下载字帖图片
        // 3.合成图片
        // 4.上传图片到oss上
        // 5.返回url
        // 获取字帖url的list
        List<String> characterUrlList = copybookCharacterInformationList.stream()
                .map(CopybookCharacterInformationEntity::getCopybookCharacter)
                .collect(Collectors.toList());

        // 保存图片的临时路径
        String tokenRe = token.replace(":", "\\");
        String savePath = "/tmp/copybookCharacter/"+tokenRe+"/";
        //savePath = "e:\\"+tokenRe+"\\";
        // 字格背景图url
        String characterBgUrl = "https://anhuihanzhi-shufa-client.oss-cn-hangzhou.aliyuncs.com/2023/05/1655def1ccbf114abc887e280db7e17b1emizige.png";
        String copybookCaracterPic = createCopybookCaracterPic(characterUrlList, characterBgUrl, savePath);
        return ResponseData.success(copybookCaracterPic);
    }



    private String createCopybookCaracterPic(List<String> characterUrlList,
                                             String characterBgUrl,
                                             String savePath){

        // 1下载字、字格图片
        String suffix = characterBgUrl.substring(characterBgUrl.lastIndexOf("."));
        // 当前时间戳
        long time = System.currentTimeMillis();
        String md5 = MD5.encrypt(characterBgUrl + time);
        String characterBgPath = savePath + md5 + suffix;
        Download.download(characterBgUrl, md5 + suffix, savePath);


        // 2生成合成图片的List<BufferedImage>
        int size = 200;
        List<BufferedImage> imagesList = new ArrayList<>();
        for (String characterUrl: characterUrlList) {
            if (characterUrl == null){
                // 如果字为空
                try {
                    BufferedImage mergeBufferedImage = Thumbnails.of(characterBgPath)
                            .size(size, size)
                            .imageType(BufferedImage.TYPE_INT_ARGB)
                            //将生成的缩略图写入文件
                            .asBufferedImage();
                    imagesList.add(mergeBufferedImage);
                } catch (IOException e) {
                    return "";
                }
                continue;
            }
            suffix = characterUrl.substring(characterUrl.lastIndexOf("."));
            md5 = MD5.encrypt(characterUrl);
            Download.download(characterUrl, md5 + suffix, savePath);
            // 将字图和字格图合成
            try {
                BufferedImage watermarkBufferedImage = Thumbnails.of(new File(savePath + md5 + suffix))
                        .size(size,size)
                        .outputQuality(1.0)
                        .imageType(BufferedImage.TYPE_INT_ARGB)
                        .asBufferedImage();
                BufferedImage mergeBufferedImage = Thumbnails.of(characterBgPath)
                        .size(size, size)
                        //指定图片类型是支持Alpha通道
                        .watermark(Positions.CENTER, watermarkBufferedImage, 1.0f)
                        .imageType(BufferedImage.TYPE_INT_ARGB)
                        //将生成的缩略图写入文件
                        .asBufferedImage();
                imagesList.add(mergeBufferedImage);
            } catch (IOException e) {
                return "";
            }
        }
        // 3制作字帖图
        // 字间距大小
        int distance = size/10;
        // 计算画布宽度、长度
        int width = characterUrlList.size();
        int widthCanvas = size + 2*distance;
        int lengthCanvas = size*width + (width+1)*distance;
        // 创建一个画布图片
        BufferedImage canvas = new BufferedImage(lengthCanvas,widthCanvas,BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = canvas.createGraphics();
        // 设置颜色为218，223，224
        graphics.setColor(new Color(218,223,224));
        // 填充颜色
        graphics.fillRect(0, 0, lengthCanvas, widthCanvas);
        int startX = distance;
        int startY = distance;
        for (int i = 0; i < width; i++) {
            graphics.drawImage(imagesList.get(i), startX, startY, size, size, null);
            startX += (size + distance);
        }
        graphics.dispose();
        String outputFilePath = savePath + "layout" + md5 + suffix;
        File outputFile = new File(outputFilePath);
        try {
            ImageIO.write(canvas, "png", outputFile);
        } catch (IOException e) {
            return "";
        }
        // 4上传字帖图
        R upload = ossFeign.uploadZip(outputFilePath);
        String layoutOssSrc = (String) upload.get("url");
        // 5移除目录下的所有文件
        File directory = new File(savePath);
        if (directory.exists() && directory.isDirectory()){
            File[] files = directory.listFiles();
            for (File file : files) {
                if (file.exists())  file.delete();
            }
            directory.delete();
        }
        // 6返回字帖图url
        return layoutOssSrc;
    }


    /**
     * 生成字帖临摹碑帖
     */
    @ApiOperation("生成字帖临摹碑帖")
    @PostMapping("/copybookcharacterlayout/get")
    public ResponseData copybookCharacterLayoutGet(@RequestBody CopybookIdsVo copybookIdsVo, @RequestHeader("Authorization") String token) {
        // 1.根据id查询图片url
        List<Long> idList = copybookIdsVo.getIds();
        if (idList == null || idList.size() < 1)
            return ResponseData.success("未生成书法图片", false);
        List<CopybookCharacterInformationEntity> copybookCharacterInformationList = copybookCharacterInformationService.getCopybookCharacterInforByIds(idList);

        // 2.下载字帖图片
        // 3.合成图片
        // 4.上传图片到oss上
        // 5.返回url
        // 获取字帖url的list
        List<String> characterUrlList = copybookCharacterInformationList.stream()
                .map(CopybookCharacterInformationEntity::getCopybookCharacter)
                .collect(Collectors.toList());
        // 传入idList顺序对应字是否查询的到的List
        List<Boolean> isExist = new ArrayList<>();
        int p = 0;
        for (int i = 0; i<idList.size(); ++i){
            Long id = idList.get(i);
            if (copybookCharacterInformationList == null || p >= copybookCharacterInformationList.size()){
                isExist.add(false);
                continue;
            }
            CopybookCharacterInformationEntity copybookCharacterInformation = copybookCharacterInformationList.get(p);
            if (!id.equals(copybookCharacterInformation.getId())){
                isExist.add(false);
                continue;
            }
            isExist.add(true);
            p++;
        }

        // 保存图片的临时路径
        String tokenRe = token.replace(":", "\\");
        String savePath = "/tmp/copybookCharacterLayout/"+tokenRe+"/";
        //savePath = "e:\\copybookCharacterLayout\\"+tokenRe+"\\";
        // 获取字格背景图url
        Long chrBgOptionId = copybookIdsVo.getChrBgOptionId();
        FixedInformationDicEntity chrBackground = fixedInformationDicService.getById(chrBgOptionId);
        String characterBgUrl = chrBackground.getFixedInformationContent();
        // 模板长度
        Integer layoutLength = copybookIdsVo.getLayoutLength();
        // 计算出模板宽度
        if (layoutLength <= 0)
            return ResponseData.success("宽度不能小于0", false);
        Integer layoutWidth = (isExist.size()-1)/layoutLength + 1;

        String copybookCaracterPic = createCopybookCharacterLayout(isExist,
                characterUrlList,
                characterBgUrl,
                savePath,
                layoutWidth,
                layoutLength,
                200);
        return ResponseData.success(copybookCaracterPic);
    }

    private String createCopybookCharacterLayout(List<Boolean> isExist,
                                                 List<String> characterUrlList,
                                                 String characterBgUrl,
                                                 String savePath,
                                                 int width,
                                                 int length,
                                                 int size){
        // 1下载字、字格图片
        String suffix = characterBgUrl.substring(characterBgUrl.lastIndexOf("."));
        long time = System.currentTimeMillis();
        String md5 = MD5.encrypt(characterBgUrl + time);
        String characterBgPath = savePath + md5 + suffix;
        Download.download(characterBgUrl, md5 + suffix, savePath);


        // 2生成合成图片的List<BufferedImage>
        List<BufferedImage> imagesList = new ArrayList<>();
        int p = 0;
        for (int i=0; i<isExist.size(); ++i) {
            if (!isExist.get(i)){
                // 如果字为空
                try {
                    BufferedImage mergeBufferedImage = Thumbnails.of(characterBgPath)
                            .size(size, size)
                            .imageType(BufferedImage.TYPE_INT_ARGB)
                            //将生成的缩略图写入文件
                            .asBufferedImage();
                    imagesList.add(mergeBufferedImage);
                } catch (IOException e) {
                    return "";
                }
                continue;
            }
            String characterUrl = characterUrlList.get(p++);

            suffix = characterUrl.substring(characterUrl.lastIndexOf("."));
            md5 = MD5.encrypt(characterUrl);
            Download.download(characterUrl, md5 + suffix, savePath);
            // 将字图和字格图合成
            try {
                BufferedImage watermarkBufferedImage = Thumbnails.of(new File(savePath + md5 + suffix))
                        .size(size,size)
                        .outputQuality(1.0)
                        .imageType(BufferedImage.TYPE_INT_ARGB)
                        .asBufferedImage();
                BufferedImage mergeBufferedImage = Thumbnails.of(characterBgPath)
                        .size(size, size)
                        //指定图片类型是支持Alpha通道
                        .watermark(Positions.CENTER, watermarkBufferedImage, 1.0f)
                        .imageType(BufferedImage.TYPE_INT_ARGB)
                        //将生成的缩略图写入文件
                        .asBufferedImage();
                imagesList.add(mergeBufferedImage);
            } catch (IOException e) {
                return "";
            }
        }
        // 3制作模板图
        // 字间距大小
        int nums = isExist.size();
        int distance = size/10;
        // 计算画布宽度、长度
        int widthCanvas = size*width + (width+1)*distance;
        int lengthCanvas = length >= nums ? (size*nums + (nums+1)*distance):(size*length + (length+1)*distance);
        // 创建一个画布图片
        BufferedImage canvas = new BufferedImage(lengthCanvas,widthCanvas,BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = canvas.createGraphics();
        // 设置颜色为218，223，224
        graphics.setColor(new Color(218,223,224));
        // 填充颜色
        graphics.fillRect(0, 0, lengthCanvas, widthCanvas);
        int startX = distance;
        int startY = distance;
        int level = 0; // 层数

        for (int i = 0; i < nums; i++) {
            // 每层第一个
            if (i%length == 0) {
                ++level;
                if (level >= 2)  startY += (size + distance);

                if (level == (nums-1)/length+1){
                    // 最后一层
                    // 最后一层多少个字格
                    int num = nums - (level - 1) * length;
                    // 该层字格+间隔的长度
                    int l = (num-1) * distance + num * size;
                    startX = (lengthCanvas - l) / 2;
                }else {
                    // 非最后一层
                    startX = distance;
                }
            }
            graphics.drawImage(imagesList.get(i), startX, startY, size, size, null);
            startX += (distance + size);
        }

        graphics.dispose();
        String outputFilePath = savePath + "layout" + md5 + suffix;
        File outputFile = new File(outputFilePath);
        try {
            ImageIO.write(canvas, "png", outputFile);
        } catch (IOException e) {
            return "";
        }
        // 4上传模板图
        R upload = ossFeign.uploadZip(outputFilePath);
        String layoutOssSrc = (String) upload.get("url");
        // 5移除目录下的所有文件
        File directory = new File(savePath);
        if (directory.exists() && directory.isDirectory()){
            File[] files = directory.listFiles();
            for (File file : files) {
                if (file.exists())  file.delete();
            }
            directory.delete();
        }
        // 6返回模板图url
        return layoutOssSrc;
    }

}
